home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-02-12 | 7.8 KB | 327 lines | [TEXT/CWIE] |
- // CCMArea version 1.3
- // 11-11-97
- // by David Catmull
-
- /* History:
-
- 10-21-97 First version
-
- 10-22-97 Added FindSuperCMArea
-
- 11-11-97 Added sCmdStringID and delay click
-
- 11-22-97 AdjustCursor returns false when CMM not present
-
- 11-29-97 Added AppendMenuCommand
-
- 12-2-97 Uncommented call to UCursor for PowerPlant 1.8
-
- 12-9-97 AddCommandToMenu initializes enabled and usesMark to false
-
- 2-10-98 Fixed clicks in title bars of windows behind modal dialogs
- */
-
- #include "UCMArea.h"
- #include "CCMArea.h"
- #include <LCommander.h>
- #include <LMenuBar.h>
- #include <LMenu.h>
- #include <LPane.h>
-
- #include <ContextualMenu.h>
- #include <Appearance.h>
-
- Boolean UCMArea::sCMPresent = false,
- UCMArea::sDelayClick = false;
- ResIDT UCMArea::sCursorID = 999,
- UCMArea::sCmdStringID = 999;
- CursHandle UCMArea::sCMCursor = 0L;
- long UCMArea::sDelay = 0;
-
- const short modifierKeys = controlKey | optionKey | cmdKey | shiftKey | alphaLock;
- const ResIDT kCMCursorID = -20488;
-
- /* ------------------------------------------------------------------------------------------------ */
- // Initialize
- // Add the command with the given ID to the given menu
-
- void
- UCMArea::Initialize()
- {
- OSErr err;
- long response;
-
- err = ::Gestalt(gestaltContextualMenuAttr,&response);
- sCMPresent = (err == noErr) && (1 << gestaltContextualMenuPresent);
-
- if (sCMPresent) {
- ::InitContextualMenus();
- GetCMCursor();
- }
- }
-
- /* ------------------------------------------------------------------------------------------------ */
- // GetCMCursor
- // Read in the CM cursor, checking for the Appearance cursor first
-
- void
- UCMArea::GetCMCursor()
- {
- if (sCMCursor)
- ::ReleaseResource((Handle)sCMCursor);
-
- sCMCursor = ::GetCursor(kCMCursorID);
- if (!sCMCursor)
- sCMCursor = ::GetCursor(sCursorID);
- }
-
- /* ------------------------------------------------------------------------------------------------ */
- // AddCommandToMenu
- // Add the command with the given ID to the given menu
- // Unless inOverrideDisable is true, disabled items are skipped
- // Use this function to build menus more easily
-
- Boolean
- UCMArea::AddCommandToMenu(MenuHandle inMenu,CommandT inCommand,Boolean inOverrideDisable)
- {
- LMenuBar *menuBar = LMenuBar::GetCurrentMenuBar();
- LMenu *menu = 0L;
-
- if (!inOverrideDisable) {
- Boolean enabled = false,usesMark = false;
- Char16 mark;
- Str255 name;
-
- LCommander::GetTarget()->ProcessCommandStatus(inCommand,enabled,usesMark,mark,name);
- if (!enabled)
- return false;
- }
-
- menuBar->FindNextMenu(menu);
-
- do {
- short item;
-
- item = menu->IndexFromCommand(inCommand);
- if (item > 0) {
- MenuHandle menuH = menu->GetMacMenuH();
- Str255 text;
-
- ::GetMenuItemText(menuH,item,text);
- ::AppendMenu(inMenu,text);
- ::SetMenuItemCommandID(inMenu,::CountMenuItems(inMenu),inCommand);
-
- return true;
- }
- } while (menuBar->FindNextMenu(menu));
-
- return false;
- }
-
- /* ------------------------------------------------------------------------------------------------ */
- // AppendMenuCommand
- // Append a menu item and set its command id
-
- void
- UCMArea::AppendMenuCommand(MenuHandle inMenu,Str255 inItemText,CommandT inCommand)
- {
- ::AppendMenu(inMenu,inItemText);
- ::SetMenuItemCommandID(inMenu,::CountMenuItems(inMenu),inCommand);
- }
-
- /* ------------------------------------------------------------------------------------------------ */
- // FindSuperCMArea
- // Find the closest superView that is a CCMArea
-
- void
- UCMArea::FindSuperCMArea(LPane *inPane,CCMArea *&outSuperCMArea,LView *&outSuperView)
- {
- CCMArea *area;
- LView *view;
-
- for (view = inPane->GetSuperView(); view; view = view->GetSuperView()) {
- area = dynamic_cast<CCMArea*>(view);
- if (area)
- break;
- }
-
- outSuperCMArea = area;
- if (area)
- outSuperView = view;
- else
- outSuperView = 0L;
- }
-
- /* ------------------------------------------------------------------------------------------------ */
- // SetCMCursor
- // Display the contextual menu cursor
-
- void
- UCMArea::SetCMCursor()
- {
- UCursor::SetTheCursor(sCursorID);
- }
-
- /* ------------------------------------------------------------------------------------------------ */
- // WaitDelayClick
- // Return true if the mouse stays down in the same place
- // Like the opposite of WaitMouseMoved, only with a time limit
-
- Boolean
- UCMArea::WaitDelayClick(const EventRecord &inEvent)
- {
- long limit;
-
- if (!::StillDown())
- return false;
-
- if (sDelay > 0)
- limit = inEvent.when + sDelay;
- else
- limit = inEvent.when + GetDblTime();
-
- while (StillDown() && (TickCount() < limit)) {
- Point mouse;
-
- GetMouse(&mouse);
- ::LocalToGlobal(&mouse);
- if (!::EqualPt(mouse,inEvent.where))
- return false;
- }
- return ::StillDown();
- }
-
- /* ------------------------------------------------------------------------------------------------ */
- // EventMouseDown
- // Make sure contextual menus appear wherever appropriate
-
- Boolean
- UCMArea::EventMouseDown(const EventRecord &inMacEvent)
- {
- WindowPtr macWindowP;
- Int16 thePart;
- Boolean clickHandled = false;
- SMouseDownEvent theMouseDown;
- LWindow *windowObj;
- CCMArea *area;
-
- if (!sCMPresent)
- return false;
-
- thePart = ::FindWindow(inMacEvent.where, &macWindowP);
- if (thePart == inMenuBar)
- return false;
-
- if (!::IsShowContextualMenuClick(&inMacEvent)) {
- if ((thePart == inContent) && sDelayClick) {
- if (!WaitDelayClick(inMacEvent))
- return false;
- }
- else
- return false;
- }
-
- do {
- windowObj = LWindow::FetchWindowObject(macWindowP);
- if (!windowObj) break;
- area = dynamic_cast<CCMArea*>(windowObj);
- if (!area) break;
-
- theMouseDown.wherePort = inMacEvent.where;
- windowObj->GlobalToPortPoint(theMouseDown.wherePort);
- theMouseDown.whereLocal = theMouseDown.wherePort;
- theMouseDown.macEvent = inMacEvent;
- theMouseDown.delaySelect = false;
-
- switch (thePart) {
-
- case inDrag:
- case inGrow:
- case inGoAway:
- case inZoomIn:
- case inZoomOut:
- // Don't handle inactive windows when there's a modal dialog
- if (!UDesktop::WindowIsSelected(windowObj))
- if (!UDesktop::FrontWindowIsModal()) {
- UDesktop::SelectDeskWindow(windowObj);
- windowObj->Activate();
- windowObj->UpdatePort();
- area->CMClick(theMouseDown);
- clickHandled = true;
- }
- break;
-
- case inContent:
- do {
- LPane *hitPane;
- LView *superView;
- Point local = theMouseDown.wherePort;
-
- if (!UDesktop::FrontWindowIsModal()) {
- if (!UDesktop::WindowIsSelected(windowObj)) {
- UDesktop::SelectDeskWindow(windowObj);
- windowObj->Activate();
- windowObj->UpdatePort();
- }
- }
- else if (windowObj != UDesktop::FetchTopModal())
- break;
-
- hitPane = windowObj->FindDeepSubPaneContaining(local.h,local.v);
- if (!hitPane) hitPane = windowObj;
-
- if (hitPane->IsEnabled() && hitPane->IsActive() &&
- dynamic_cast<CCMArea*>(hitPane))
- break; // Active CCMAreas can handle it themselves
-
- // Find the deepest owning superView that's a CCMArea
- // That could be the window
-
- FindSuperCMArea(hitPane,area,superView);
-
- if (!area) {
- area = dynamic_cast<CCMArea*>(windowObj);
- if (!area)
- break;
- }
-
- area->CMClick(theMouseDown);
- clickHandled = true;
- } while (false);
- }
- } while (false);
-
- return clickHandled;
- }
-
- /* ------------------------------------------------------------------------------------------------ */
- // AdjustCursor
- // Make sure the CM cursor appears where appropriate
-
- Boolean
- UCMArea::AdjustCursor(const EventRecord &inMacEvent)
- {
- WindowPtr windowPtr;
- LWindow *windowObj;
-
- if (!sCMPresent)
- return false;
-
- // Look for inactive CCMWindows
- do {
- if ((inMacEvent.modifiers & modifierKeys) != controlKey) // Control key only
- break;
-
- ::FindWindow(inMacEvent.where,&windowPtr);
- if (!windowPtr) break;
- windowObj = LWindow::FetchWindowObject(windowPtr);
- if (!windowObj) break;
- if (!dynamic_cast<CCMArea*>(windowObj)) break;
-
- UCMArea::SetCMCursor();
- return true;
- } while (false);
-
- return false;
- }
-